﻿/// <summary>
/// 功能：通用函数类，和业务逻辑无关的多次使用的工具函数
/// 创建：朱世强
/// 日期：2015.6
/// </summary>
using UnityEngine;
using System.Collections;
using System;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Text.RegularExpressions;
using System.Net.NetworkInformation;


public static class CommonFun
{

    public static Vector2 vc2 = new Vector2();
    public static Vector3 vc3 = new Vector3();

    #region URL
    private static string streamingAssetsURLPath = null;
    public static string GetStreamingAssetsURLPath()
    {
        if (string.IsNullOrEmpty(streamingAssetsURLPath))
        {
            streamingAssetsURLPath =
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
                @"file://" + Application.dataPath + "/StreamingAssets";
#elif UNITY_ANDROID
				@"jar:file://" + Application.dataPath + "!/assets";
#elif UNITY_IPHONE
				@"file://" + Application.dataPath + "/Raw";
#else
				string.Empty;
#endif
        }

        return streamingAssetsURLPath;
    }

    private static string temporaryCachePathURLPath = null;
    public static string GetTemporaryCachePathURLPath()
    {
        if (string.IsNullOrEmpty(temporaryCachePathURLPath))
        {
            temporaryCachePathURLPath =
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
                @"file:///" + Application.temporaryCachePath;
#elif UNITY_ANDROID
				@"file:///" + Application.temporaryCachePath;
#elif UNITY_IPHONE
				@"file:///" + Application.temporaryCachePath;
#else
				string.Empty;
#endif
        }

        return temporaryCachePathURLPath;
    }

    private static string persistentDataPathURLPath = null;
    public static string GetPersistentDataPathURLPath()
    {
        if (string.IsNullOrEmpty(persistentDataPathURLPath))
        {
            persistentDataPathURLPath =
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
                @"file:///" + Application.persistentDataPath;
#elif UNITY_ANDROID
				@"file:///" + Application.persistentDataPath;
#elif UNITY_IPHONE
				@"file:///" + Application.persistentDataPath;
#else
				string.Empty;
#endif
        }

        return persistentDataPathURLPath;
    }
    #endregion

    #region UGUI设置父对象
    /// <summary>
    /// UGUI根据父对象归一化
    /// </summary>
    /// <param name="parent">Parent.</param>
    /// <param name="child">Child.</param>
    /// <param name="show">If set to <c>true</c> show.</param>
    public static void SetGameObjectParent(RectTransform parent, RectTransform child, bool show = true)
    {
        child.SetParent(parent);

        child.localScale = Vector3.one;
        child.localRotation = Quaternion.Euler(Vector3.zero);
        child.anchorMin = Vector2.zero;
        child.anchorMax = Vector2.one;
        child.offsetMin = Vector2.zero;
        child.offsetMax = Vector2.zero;
        child.localPosition = Vector3.zero;
        child.gameObject.SetActive(show);
    }

    /// <summary>
    /// 移除一个组件，不能去掉Component限定，不能des obj
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="component"></param>
    public static void RemoveCompent<T>(T component) where T : Component
    {
        Component.Destroy(component);
    }

    /// <summary>
    /// 普通对象父对象归一化
    /// </summary>
    /// <param name="parent"></param>
    /// <param name="child"></param>
    /// <param name="show"></param>
    public static void SetGameObjectParent(Transform parent, Transform child, bool show = true)
    {
        if (parent == null || child == null)
            return;
        child.SetParent(parent);
        child.localScale = Vector3.one;
        child.localRotation = Quaternion.Euler(Vector3.zero);
        child.localPosition = Vector3.zero;
        child.gameObject.SetActive(show);
    }

    //根据每秒速度获取每帧速度
    public static float GetSpeed(float speed)
    {
        return speed * Time.deltaTime;
    }

    //根据名字查询transform下所有对象，如果名称一样，则返回最近一个
    public static Transform TransformFindByName(Transform parent, string name)
    {
        Transform ret = null;
        var allTranforms = parent.GetComponentsInChildren<Transform>();
        for (int i = 0; i < allTranforms.Length; i++)
        {
            if (allTranforms[i].gameObject.name == name)
            {
                ret = allTranforms[i];
                break;
            }
        }
        return ret;
    }

    public static float GetFixedSpeed(float speed)
    {
        return speed * Time.fixedDeltaTime;
    }
    #endregion


    #region 时间ticks
    /// <summary>
    /// Gets the time ticks.获取一个int的时间，一天内的，毫秒计算
    /// </summary>
    /// <returns>The time ticks.</returns>
    public static int GetTimeTicks()
    {
        var ts = new TimeSpan(DateTime.Now.Ticks);
        return ts.Hours * 3600000 + ts.Seconds * 60000 + ts.Minutes * 1000 + ts.Milliseconds;
    }
    #endregion

    #region   时间戳

    /// <summary>
    ///  获取时间戳（毫秒）
    /// </summary>
    /// <param name="time"></param>
    /// <returns></returns>
    public static long ConvertDateTimeToLongMS(DateTime time)
    {
        return (time.ToUniversalTime().Ticks - 621355968000000000) / 10000;
    }

    /// <summary>
    ///  获取时间戳（秒）
    /// </summary>
    /// <param name="time"></param>
    /// <returns></returns>
    public static long ConvertDateTimeToLongS(DateTime time)
    {
        return (time.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
    }

    /// <summary>
    /// 将时间戳转换为DateTime
    /// </summary>
    /// <param time="longtime">时间戳单位秒</param>
    /// <returns></returns>
    public static DateTime ConvertIntToDateTime(int time)
    {
        DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区
        DateTime dt = startTime.AddSeconds(time);
        return dt;
        //System.Console.WriteLine(dt.ToString("yyyy/MM/dd HH:mm:ss:ffff"));
    }
    /// <summary>
    /// 将秒转换为时分秒
    /// </summary>
    /// <param name="seconds"></param>
    /// <returns></returns>
    public static string SecondToHMS(int seconds)
    {
        TimeSpan ts = new TimeSpan(0, 0, seconds);
        string str = "";
        if (ts.Days > 0)
        {
            str = string.Format("{0}天", ts.Days) + string.Format("{0:00}", ts.Hours) + ":" + string.Format("{0:00}", ts.Minutes) + ":" + string.Format("{0:00}", ts.Seconds);
        }
        else if (ts.Days == 0 && ts.Hours > 0)
        {
            str = string.Format("{0:00}", ts.Hours) + ":" + string.Format("{0:00}", ts.Minutes) + ":" + string.Format("{0:00}", ts.Seconds);
        }
        else if (ts.Days == 0 && ts.Hours == 0 && ts.Minutes > 0)
        {
            str = "00:" + string.Format("{0:00}", ts.Minutes) + ":" + string.Format("{0:00}", ts.Seconds);
        }
        else if (ts.Days == 0 && ts.Hours == 0 && ts.Minutes == 0 && ts.Seconds > 0)
        {
            str = "00:00:" + string.Format("{0:00}", ts.Seconds);
        }

        return str;
    }

    #endregion

    #region 根据角度和长度获得绕一个点的一个点
    //根据角度和长度获得绕（0,0,0）的一个点
    public static Vector3 RotateAround(Vector3 worldPos, float worldAngle, float targetDisance, float targetAngle)
    {
        Vector3 vc3 = new Vector3();
        vc3.z = (float)Math.Cos(AngleToRadian(worldAngle + targetAngle)) * targetDisance;
        vc3.x = (float)Math.Sin(AngleToRadian(worldAngle + targetAngle)) * targetDisance;
        return vc3 + worldPos;
    }
    #endregion

    #region 搜敌

    //判断一个点是否在一个四边形区域之内,XY平面
    public static bool CheckPointInQua(Vector2 a, Vector2 b, Vector2 c, Vector2 d, Vector3 target)
    {
        Vector2 m = new Vector2(target.x, target.y);
        var ab = b - a;
        var am = m - a;
        //var ad = d - a;
        var bc = c - b;
        var bm = m - b;
        //var ba = a - b;
        var cd = d - c;
        var cm = m - c;
        //var cb = b - c;
        var da = a - d;
        var dm = m - d;
        //var dc = c - d;
        if (Vector2.Dot(ab, am) >= 0 && Vector2.Dot(bc, bm) >= 0 && Vector2.Dot(cd, cm) >= 0 && Vector2.Dot(da, dm) >= 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /// <summary>
    /// 判定一个点是否在四边形区域内，XY平面，忽略Z深度
    /// </summary>
    /// <param name="center">起始点</param>
    /// <param name="isFace">是否为正方向</param>
    /// <param name="angle"></param>
    /// <param name="disance">距离</param>
    /// <param name="target">目标</param>
    /// <param name="quadrilateral_y">检测半径Y</param>
    /// <returns></returns>
    public static bool CheckPointIsInSector(Vector3 center, bool isFaceX, float disance, Vector3 target, float quadrilateral_y)
    {
        var yAbs = Mathf.Abs(center.y - target.y);
        if (yAbs > quadrilateral_y)
        {
            return false;
        }
        var abs = Mathf.Abs(center.x - target.x);
        if (abs < disance)
        {
            if (isFaceX && center.x < target.x)
            {
                return true;
            }
            else if (isFaceX == false && center.x > target.x)
            {
                return true;
            }
            else if (abs < 0.1f)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    #endregion

    #region 角度 弧度 转换
    //角度转弧度
    public static float AngleToRadian(float angle)
    {
        return Mathf.PI / 180 * angle;
    }

    //弧度转角度
    public static float RadianToAngle(float Radian)
    {
        return 180 / Mathf.PI * Radian;
    }
    #endregion

    #region  获取两点之间的一个点,向量运算
    /// <summary>
    /// 获取朝向结束点上的直线上的一个点,在方法中进行了向量的减法，以及乘法运算
    /// </summary>
    /// <param name="start">起始点</param>
    /// <param name="end">结束点</param>
    /// <param name="distance">距离</param>
    /// <returns></returns>
    public static Vector3 GetBetweenPoint(Vector3 start, Vector3 end, float distance)
    {
        Vector3 normal = (end - start).normalized;
        return normal * distance + start;
    }

    //获取指向结束点直线上的一个点,从开始点算距离
    public static Vector3 GetLinePoint(Vector3 start, Vector3 end, float distance)
    {
        Vector3 normal = (end - start).normalized;
        return normal * distance + start;
    }
    #endregion

    #region XY判距
    //XY平面判距
    public static float DistanceXY(Vector3 a, Vector3 b)
    {
        return Vector3.Distance(new Vector3(a.x, a.y, 0), new Vector3(b.x, b.y, 0));
    }
    #endregion

    #region xz lookat
    //忽略xz的lookat
    public static void LookAt(Transform ts, Transform target)
    {
        if (ts == null || target == null)
            return;
        ts.LookAt(target);
        var vc3 = ts.rotation.eulerAngles;
        vc3.x = 0;
        vc3.z = 0;
        ts.rotation = Quaternion.Euler(vc3);
    }

    //忽略xz的lookat pos
    public static void LookAtPos(Transform ts, Vector3 target)
    {
        if (ts == null)
        {
            return;
        }
        var to = target - ts.position;
        vc2.x = 0;
        vc2.y = 1;
        var v = vc2;
        vc2.x = to.x;
        vc2.y = to.z;
        var b = vc2;
        var angle = angle_360(v, b);
        vc3.x = 0;
        vc3.y = angle;
        vc3.z = 0;
        var v3 = vc3;
        ts.localRotation = Quaternion.Euler(v3);
    }


    //角度计算
    public static float angle_360(Vector2 from_, Vector2 to_)
    {
        if (Vector3.Normalize(to_).x < 0)
        {
            return -Vector2.Angle(from_, to_);
        }
        else
        {
            return Vector2.Angle(from_, to_);
        }

    }
    #endregion

    #region 世界坐标转ui坐标
    public static Vector3 GetWorldPointToUIPos(Camera uiCamera, Camera worldCamera, Vector3 pos)
    {
        return uiCamera.ScreenToWorldPoint(worldCamera.WorldToScreenPoint(pos));
    }
    #endregion

    #region 归一化对象
    public static void NormalTransform(RectTransform ts)
    {
        ts.localPosition = Vector3.zero;
        ts.localScale = Vector3.one;
        ts.localRotation = Quaternion.Euler(Vector3.zero);
    }
    #endregion

    #region 获取周围的点,centerPos为正向坐标，和世界坐标无关
    /// <summary>
    /// 获取周围的点,centerPos为正向坐标，和世界坐标无关
    /// </summary>
    public static Vector3[] GetPointByCenter(float distance, Vector3 centerPos)
    {
        return null;//后续扩展
    }
    #endregion

    #region 获取地面有效点
    /// <summary>
    /// 获取有效的地面点
    /// </summary>
    /// <returns><c>true</c> if is valid point; otherwise, <c>false</c>.</returns>
    public static bool IsValidPoint(Vector3 pos)
    {
        return true;//后续拓展
    }
    #endregion

    #region 获取局部坐标
    /// <summary>
    /// 以world为世界中心，target在world的局部坐标
    /// </summary>
    /// <returns>The space position.</returns>
    /// <param name="target">Target.</param>
    /// <param name="world">World.</param>
    public static Vector3 GetSpacePos(Vector3 target, Vector3 world)
    {
        var v = target - world;
        return v;
    }
    #endregion


    #region 屏幕射线检测可用CObjectCharacter角色对象guid
    public static int ScreenPointToRay()
    {
        int guid = -1;
        Vector3 vc3;
        if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
        {
            vc3 = Input.touches[0].position;
        }
        else
        {
            vc3 = Input.mousePosition;
        }
        /*Ray ray = CameraManager.Instance.MainCamera.ScreenPointToRay (vc3);
        RaycastHit hitInfo;
        if (Physics.Raycast (ray, out hitInfo)) 
        {
            var gameObj = hitInfo.collider.gameObject;
            if(gameObj != null)
            {
                var c = gameObj.GetComponent<CObjectCharacter> ();
                if(c != null)
                {
                    guid = c.Guid;
                }
            }
        }*/
        return guid;
    }
    #endregion


    #region 格子
    public static Vector3[] GetSlot(Vector3 center, float length, int width, int height)
    {
        Vector3[] vc = new Vector3[width * height];
        int index = 1;
        for (int i = 0; i < height; i++)
        {
            float x = height * length - length / 2f - (float)i * length;
            float y = length / 2;
            for (int j = 0; j < width;)
            {
                vc3.x = x;
                vc3.y = 0f;
                vc3.z = y;
                vc[index - 1] = GetSpacePos(vc3, center);
                vc[index - 1].z += (-length * (float)width) / 2f;
                vc[index - 1].x += (-length * (float)height) / 2f;
                j++;
                y = (float)j * length + length / 2f;
                index++;
            }
        }
        return vc;
    }
    #endregion

    #region 多级查询对象
    public static RectTransform GetTransform(RectTransform parent, string transformName)
    {
        foreach (RectTransform ts in parent)
        {
            if (ts.name != transformName)
            {
                var chile = GetTransform(ts, transformName);
                if (chile != null)
                {
                    return chile;
                }
            }
            else
            {
                return ts;
            }
        }
        return null;
    }
    #endregion

    /// <summary>
    /// Base64加密
    /// </summary>
    /// <param name="codeName">加密采用的编码方式</param>
    /// <param name="source">待加密的明文</param> 
    /// <returns></returns>
    public static string EncodeBase64(Encoding encode, string source)
    {
        byte[] bytes = encode.GetBytes(source);
        var str = "";
        try
        {
            str = Convert.ToBase64String(bytes);
        }
        catch
        {
            str = source;
        }
        return str;
    }

    /// <summary>
    /// Base64加密，采用utf8编码方式加密
    /// </summary>
    /// <param name="source">待加密的明文</param>
    /// <returns>加密后的字符串</returns>
    public static string Base64Encode(string source)
    {
        var ncode = EncodeBase64(Encoding.UTF8, source);
        return ncode;
    }

    /// <summary>
    /// Base64解密
    /// </summary>
    /// <param name="codeName">解密采用的编码方式，注意和加密时采用的方式一致</param>
    /// <param name="result">待解密的密文</param>
    /// <returns>解密后的字符串</returns>
    public static string DecodeBase64(Encoding encode, string result)
    {
        string decode = "";
        byte[] bytes = Convert.FromBase64String(result);
        try
        {
            decode = encode.GetString(bytes);
        }
        catch
        {
            decode = result;
        }
        return decode;
    }

    /// <summary>
    /// Base64解密，采用utf8编码方式解密
    /// </summary>
    /// <param name="result">待解密的密文</param>
    /// <returns>解密后的字符串</returns>
    public static string Base64Decode(string result)
    {
        return DecodeBase64(Encoding.UTF8, result);
    }

    /// <summary>
    /// string md5
    /// </summary>
    /// <returns>The d5 encrypt.</returns>
    /// <param name="strText">String text.</param>
    public static string StringToMD5(string strText)
    {
        MD5 md5 = new MD5CryptoServiceProvider();
        byte[] result = md5.ComputeHash(System.Text.Encoding.Default.GetBytes(strText));
        return System.Text.Encoding.Default.GetString(result);
    }

    public static string Asc(string str)
    {
        string ret = "";
        var l = System.Text.Encoding.Default.GetBytes(str);
        for (int i = 0; i < l.Length - 1; i++)
        {
            System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
            ret += (asciiEncoding.GetBytes(str[i].ToString())[0]).ToString();
        }
        return ret;
    }

    #region 点相对于transform朝向的正角度0-360
    public static float ComputAngle(Vector3 pos, Transform ts)
    {
        var localPos = GetSpacePos(pos, ts.position);
        localPos.y = 0;
        var angle = Vector3.Angle(localPos.normalized, new Vector3(0, 0, 1));
        if (localPos.x < 0)
        {
            angle = 360 - angle;
        }
        angle = angle - ts.eulerAngles.y;
        if (angle < 0)
        {
            angle = 360 + angle;
        }
        return angle;
    }
    #endregion

    #region 像素转分辨率
    public static Vector2 PixelsToResolution(Vector2 target)
    {
        float screenW = (float)Screen.width;
        float screenH = (float)Screen.height;
        var w = target.x / screenW;
        var y = target.y / screenH;
        var h = screenW * 1920f / screenW;
        var m = screenW * 1080f / screenW;
        vc2.x = w * h;
        vc2.y = y * m;
        return vc2;
    }
    #endregion

    #region 位偏移运算
    public static long SeralizationVc3ToLong(Vector3 value)
    {
        long yCode = 0;
        if (value.y > 0)
        {
            yCode = 1;
        }
        var currX = (long)(value.x * 100);
        var currY = (long)(Math.Abs((value.y * 100)));
        var currZ = (long)(value.z * 100);
        return (currX << 40) + (currY << 20) + (currZ << 1) + yCode;
    }

    public static Vector3 SeralizationLongToVc3(long value)
    {
        var longX = (value >> 40) << 40;
        var longY = ((value - longX) >> 20) << 20;
        var longZ = ((value - longX - longY) >> 1) << 1;
        var longYCode = value - longX - longY - longZ;
        vc3.x = ((float)(longX >> 40)) / 100f;
        vc3.y = (((float)(longY >> 20)) / 100f);
        vc3.z = ((float)(longZ >> 1)) / 100f;
        if (longYCode == 0)
        {
            vc3.y = -vc3.y;
        }
        return vc3;
    }
    #endregion

    #region 求垂直于A,B长度为distance的pos，xz平面上
    /// <summary>
    /// 求垂直于A,B长度为distance的pos，
    /// </summary>
    /// <returns>The vertical position.</returns>
    /// <param name="a">The alpha component.</param>
    /// <param name="b">The blue component.</param>
    /// <param name="distance">Distance.</param>
    public static Vector3 ComputeVerticalPos(Vector3 a, Vector3 b, float distance)
    {
        var aa = a;
        a.y = 0;
        a = a.normalized;
        b.y = 0;
        b = b.normalized;
        var vc3 = Vector3.Cross((b - a).normalized, new Vector3(0, 1, 0)).normalized;
        vc3 = (UnityEngine.Random.Range(0, 10) > 5 ? -1 : 1) * vc3 * distance;
        return vc3 + aa;
    }
    #endregion

    #region 计算字符串hash1
    /// <summary>
    /// 计算SHA-1码
    /// </summary>
    /// <param name="word">字符串</param>
    /// <param name="toUpper">返回哈希值格式 true：英文大写，false：英文小写</param>
    /// <returns></returns>
    public static string Hash_SHA_1(string word, bool toUpper = false)
    {
        /*word = word.Replace ("/", "_");
        word = word.Replace (".", "_");
        word = word.Replace ("+", "_");
        word = word.Replace ("-", "_");
        word = word.ToLower ();
        return word;*/
        try
        {
            System.Security.Cryptography.SHA1CryptoServiceProvider SHA1CSP
                = new System.Security.Cryptography.SHA1CryptoServiceProvider();
            byte[] bytValue = System.Text.Encoding.UTF8.GetBytes(word);
            byte[] bytHash = SHA1CSP.ComputeHash(bytValue);
            SHA1CSP.Clear();
            //根据计算得到的Hash码翻译为SHA-1码
            string sHash = "", sTemp = "";
            for (int counter = 0; counter < bytHash.Count(); counter++)
            {
                long i = bytHash[counter] / 16;
                if (i > 9)
                {
                    sTemp = ((char)(i - 10 + 0x41)).ToString();
                }
                else
                {
                    sTemp = ((char)(i + 0x30)).ToString();
                }
                i = bytHash[counter] % 16;
                if (i > 9)
                {
                    sTemp += ((char)(i - 10 + 0x41)).ToString();
                }
                else
                {
                    sTemp += ((char)(i + 0x30)).ToString();
                }
                sHash += sTemp;
            }
            //根据大小写规则决定返回的字符串
            return toUpper ? sHash : sHash.ToLower();
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
    #endregion

    #region 计算文件的hash1
    /// <summary>
    ///  计算指定文件的SHA1值
    /// </summary>
    /// <param name="fileName">指定文件的完全限定名称</param>
    /// <returns>返回值的字符串形式</returns>
    public static String ComputeSHA1(String fileName)
    {

        String hashSHA1 = String.Empty;
        //检查文件是否存在，如果文件存在则进行计算，否则返回空值
        if (System.IO.File.Exists(fileName))
        {
            using (System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                //计算文件的SHA1值
                System.Security.Cryptography.SHA1 calculator = System.Security.Cryptography.SHA1.Create();
                Byte[] buffer = calculator.ComputeHash(fs);
                calculator.Clear();
                //将字节数组转换成十六进制的字符串形式
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < buffer.Length; i++)
                {
                    stringBuilder.Append(buffer[i].ToString("x2"));
                }
                hashSHA1 = stringBuilder.ToString();
            }//关闭文件流
        }
        return hashSHA1;
    }
    #endregion


    public static Vector3[] GetWorldCorners(RectTransform rectTransform)
    {
        Vector3[] corners = new Vector3[4];
        rectTransform.GetWorldCorners(corners);
        return corners;
    }

    public static void EffectSetMask(RectTransform item, RectTransform mask)
    {
        Vector3[] corners = new Vector3[4];
        mask.GetWorldCorners(corners);
        var minX = corners[0].x;
        var minY = corners[0].y;
        var maxX = corners[2].x;
        var maxY = corners[2].y;

        var c = item.gameObject.GetComponentsInChildren<Renderer>(true);

        ParticleSystem[] particlesSystems = item.transform.GetComponentsInChildren<ParticleSystem>(true);

        for (int i = 0; i < c.Length; i++)
        {
            Material[] ms = c[i].materials;
            for (int j = 0; j < ms.Length; j++)
            {
                var m = ms[j];
                m.SetFloat("_MinX", minX);
                m.SetFloat("_MinY", minY);
                m.SetFloat("_MaxX", maxX);
                m.SetFloat("_MaxY", maxY);
            }
        }

        for (int i = 0; i < particlesSystems.Length; i++)
        {
            Material[] ms = particlesSystems[i].GetComponent<Renderer>().materials;
            for (int j = 0; j < ms.Length; j++)
            {
                var m = ms[j];
                m.SetFloat("_MinX", minX);
                m.SetFloat("_MinY", minY);
                m.SetFloat("_MaxX", maxX);
                m.SetFloat("_MaxY", maxY);
            }
        }
    }

    /// <summary>
    /// 图片压缩大小
    /// </summary>
    /// <returns>The texture.</returns>
    /// <param name="source">Source.</param>
    /// <param name="targetWidth">Target width.</param>
    /// <param name="targetHeight">Target height.</param>
    public static Texture2D ScaleTexture(Texture2D source, int targetWidth, int targetHeight)
    {
        Texture2D result = new Texture2D(targetWidth, targetHeight, source.format, false);
        float incX = (1.0f / (float)targetWidth);
        float incY = (1.0f / (float)targetHeight);

        for (int i = 0; i < result.height; ++i)
        {
            for (int j = 0; j < result.width; ++j)
            {
                Color newColor = source.GetPixelBilinear((float)j / (float)result.width, (float)i / (float)result.height);
                result.SetPixel(j, i, newColor);
            }
        }
        result.Apply();
        return result;
    }

    public static Texture2D GetTexByTargetWidth(Texture2D source, int targetWidth)
    {
        return ScaleTexture(source, targetWidth, (source.height * targetWidth) / source.width);
    }

    public static void SetCanvasOrder(GameObject gameObject, int order, bool needRaycaster)
    {
        Canvas canvas = gameObject.MustComponent<Canvas>();
        canvas.overrideSorting = true;
        canvas.sortingOrder = order;
        canvas.additionalShaderChannels = AdditionalCanvasShaderChannels.TexCoord1;
        if (needRaycaster)
            canvas.transform.MustComponent<UnityEngine.UI.GraphicRaycaster>();
    }

    public static void OpenUrl(string url)
    {
        Application.OpenURL(url);
    }


    public static float GetAdaptionScale()
    {

        int ManualWidth = 1920;
        int ManualHeight = 1080;
        int manualWidth;
        if (Convert.ToSingle(Screen.height) / Screen.width > Convert.ToSingle(ManualHeight) / ManualWidth)
            manualWidth = Mathf.RoundToInt(Convert.ToSingle(ManualHeight) / Screen.height * Screen.width);
        else
            manualWidth = ManualWidth;
        return Convert.ToSingle(manualWidth / 1920f);
    }


    //UTC时间搓转为本地时间搓
    public static string ConvertUTCDateTime(double d, string v)
    {
        DateTime dt = DateTime.UtcNow;
        var localDt = DateTime.Now;
        var m = dt - localDt;
        var s = m.TotalMilliseconds;
        var ld = d - s;
        return ld.ToString();
    }




    #region 特效相关


    public static void ClearTrailRenderPoint(GameObject gameObject)
    {
        if (gameObject == null)
            return;
        var m = gameObject.GetComponentsInChildren<TrailRenderer>();
        for (int i = 0; i < m.Length; i++)
        {
            m[i].Clear();
        }
    }
    #endregion


    #region 编码转换 GB2312<——>UTF8
    /// <summary>
    /// GB2312转换成UTF8
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    public static string GB2312_Utf8(byte[] bytes)
    {
        System.Text.Encoding utf8, gb2312;
        gb2312 = System.Text.Encoding.GetEncoding("gb2312");
        utf8 = System.Text.Encoding.GetEncoding("utf-8");
        bytes = System.Text.Encoding.Convert(gb2312, utf8, bytes);
        return utf8.GetString(bytes);
    }

    /// <summary>
    /// GB2312转换成UTF8
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    public static string GB2312_Utf8(string text)
    {
        System.Text.Encoding utf8, gb2312;
        gb2312 = System.Text.Encoding.GetEncoding("gb2312");
        utf8 = System.Text.Encoding.GetEncoding("utf-8");
        byte[] gb;
        gb = gb2312.GetBytes(text);
        gb = System.Text.Encoding.Convert(gb2312, utf8, gb);
        return utf8.GetString(gb);
    }

    /// <summary>
    /// UTF8转换成GB2312
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    public static string Utf8_GB2312(string text)
    {
        //声明字符集   
        System.Text.Encoding utf8, gb2312;
        //utf8   
        utf8 = System.Text.Encoding.GetEncoding("utf-8");
        //gb2312   
        gb2312 = System.Text.Encoding.GetEncoding("gb2312");
        byte[] utf;
        utf = utf8.GetBytes(text);
        utf = System.Text.Encoding.Convert(utf8, gb2312, utf);
        //返回转换后的字符   
        return gb2312.GetString(utf);
    }
    #endregion

    public static void SetLayer(this GameObject gameObject, int layer, bool isDefault = true)
    {
        if (gameObject == null) return;
        if (!isDefault || gameObject.layer == 0)
        {
            gameObject.layer = layer;
        }

        var allSkinMeshRender = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
        for (int i = 0; i < allSkinMeshRender.Length; i++)
        {
            var value = allSkinMeshRender[i];
            if (value != null)
            {
                value.gameObject.layer = layer;
            }
        }
        var allMeshRender = gameObject.GetComponentsInChildren<MeshRenderer>();
        for (int i = 0; i < allMeshRender.Length; i++)
        {
            var value = allMeshRender[i];
            if (value != null)
            {
                value.gameObject.layer = layer;
            }
        }
    }

    public static Vector3 GetPos(int x, int y, int z)
    {
        return new Vector3(
           x / 1000f,
           y / 1000f,
           z / 1000f);
    }


    //传入ui的transform,获取适配后的宽高
    public static Vector2 GetAdjustStaticUIRectTransformSize(RectTransform rectTransform)
    {
        Vector2 _retVec2 = Vector2.zero;

        if (rectTransform != null)
        {
            _retVec2 = new Vector2(rectTransform.sizeDelta.x * Screen.width / 1920f, rectTransform.sizeDelta.y * Screen.height / 1080f);
        }

        return _retVec2;
    }


    //将策划的配置表中配置的，基于设计分辨率的坐标，变为新手引导中自适应位置的坐标
    public static Vector2 TransFromStandardConfigPositionToScreenPosition(float posX, float posY, RectTransform uiRoot)
    {
        float _newPosX = -uiRoot.sizeDelta.x / 2 + posX * uiRoot.sizeDelta.x / 1920f;
        float _newPosY = -uiRoot.sizeDelta.y / 2 + posY * uiRoot.sizeDelta.y / 1080f;

        return new Vector2(_newPosX, _newPosY);
    }


    #region 判断一个点是否在三角形内
    /// <summary>
    /// 判断一个点是否在三角形内
    /// </summary>
    /// <param name="triangleA"></param>
    /// <param name="triangleb"></param>
    /// <param name="trianglec"></param>
    /// <param name="point"></param>
    /// <returns></returns>
    public static bool CheakPointInTriangle(Vector3 triangleA, Vector3 triangleb, Vector3 trianglec, Vector3 point)
    {
        Vector2 pa = GetTriangleVector(triangleA, point);
        Vector2 pb = GetTriangleVector(triangleb, point);
        Vector2 pc = GetTriangleVector(trianglec, point);

        float t1 = CrossTriangleValue(pa, pb);
        float t2 = CrossTriangleValue(pb, pc);
        float t3 = CrossTriangleValue(pc, pa);

        return t1 * t2 > 0 && t2 * t3 > 0;
    }
    //获取ab向量
    private static Vector2 GetTriangleVector(Vector3 a, Vector3 b)
    {
        return new Vector2(a.x - b.x, a.z - b.z);
    }
    //获取向量叉乘
    private static float CrossTriangleValue(Vector2 a, Vector2 b)
    {
        return a.x * b.y - a.y * b.x;
    }
    #endregion


    /// <summary>
    /// 纯数字
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static bool CheakNameAllNumber(string value)
    {
        Regex numberRegex = new Regex(@"^\d+$");//纯数字正则
        Match m = numberRegex.Match(value);
        return m.Success;
    }
    /// <summary>
    /// 根据T值，计算贝塞尔曲线上面相对应的点
    /// </summary>
    /// <param name="t"></param>T值
    /// <param name="p0"></param>起始点
    /// <param name="p1"></param>控制点
    /// <param name="p2"></param>目标点
    /// <returns></returns>根据T值计算出来的贝赛尔曲线点
    private static Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;

        Vector3 p = uu * p0;
        p += 2 * u * t * p1;
        p += tt * p2;

        return p;
    }

    /// <summary>
    /// 获取存储贝塞尔曲线点的数组
    /// </summary>
    /// <param name="startPoint"></param>起始点
    /// <param name="controlPoint"></param>控制点
    /// <param name="endPoint"></param>目标点
    /// <param name="segmentNum"></param>采样点的数量
    /// <returns></returns>存储贝塞尔曲线点的数组
    public static Vector3[] GetBeizerList(Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint, int segmentNum)
    {
        Vector3[] path = new Vector3[segmentNum];
        for (int i = 1; i <= segmentNum; i++)
        {
            float t = i / (float)segmentNum;
            Vector3 pixel = CalculateCubicBezierPoint(t, startPoint,
                controlPoint, endPoint);
            path[i - 1] = pixel;
        }
        return path;

    }
}
